#pragma once

/* bulk兼容层 */
/* 用于支持n个申请释放 */
#include <metalc/base/mlayer.h>
#include <dinfra/list.h>

DECL_MLAYER_FUNC(bulk)
DEF_MLAYER_MAXSZ(bulk, 0)
DEF_MLAYER_OBJNR(bulk, 0)

SAI void bulk_pinit(const mlfunc_t * cont){
	PARAM_USED(cont);
	INFO("bulk pinit\n");
}
SAI void bulk_tinit(const mlfunc_t * cont){
	PARAM_USED(cont);
	INFO("bulk tinit\n");
}
SAI void *bulk_alloc(mreq_t *req, const mlfunc_t * cont){
	size_t nr = req->nr;
	size_t sz = req->size;
	slist_t dummy;
	slist_t *tail = &dummy;
	size_t alloc_nr = 0;
	ASSERT(nr != 0);
	for (size_t idx = 0; idx < nr; idx++){
		req->size = sz;
		req->nr = 1;
		req->ptr = NULL;
		void *ptr = cont->lalloc(req);
		if (ptr){
			tail->next = (slist_t *)ptr;
			tail = (slist_t *)ptr;
			alloc_nr += 1;
		}
	}
	if (alloc_nr != 0){
		tail->next = NULL;
		req->ptr = (void *)dummy.next;
		req->sptr = tail;
	}else{
		req->ptr = NULL_PTR;
		req->sptr = NULL_PTR;
	}
	req->size = sz;
	req->nr = alloc_nr;
	// ASSERT(slist_len_noloop(dummy.next) == alloc_nr);
	return req->ptr;
}
SAI bool_t bulk_free(mreq_t *req, const mlfunc_t * cont){
	size_t sz = req->size;
	size_t nr = req->nr;

	slist_t *head;
	slist_t *next = (slist_t *)req->ptr;
	// slist_t *tail = (slist_t *)req->sptr;
	// ASSERT(slist_len_noloop(next) == nr);
	for (size_t idx = 0; idx < nr; idx++){
		head = next;
		next = atm_ld(&head->next);
		req->ptr = head;
		req->sptr = NULL_PTR;
		req->size = sz;
		cont->lfree(req);
	}
	return TRUE;
}
SAI size_t bulk_sizeof(mreq_t *req, const mlfunc_t * cont){
	return cont->lsizeof(req);
}
